#include <stdlib.h>

#include "edaSerialize.h"
#include "edaBestImprSelect.h"
#include "edaDefine.h"
#include "edaExpCoolingSchedule.h"
#include "edaLinearCoolingSchedule.h"
#include "edaGenContinue.h"
#include "edaFitContinue.h"
#include "edaHC.h"
#include "edaSA.h"
#include "edaTS.h"
#include "edaNoAspirCrit.h"
#include "edaImprBestFitAspirCrit.h"
#include "edaSimpleMoveTabuList.h"
#include "edaSimpleSolutionTabuList.h"

void edaSerialize::doSerialize(edaBuffer &buf, bool pack)
{
  if (pack)
  {
    int clsid = getClassID();

    buf.Pack(&clsid, 1);
  }

  this->Serialize(buf, pack);
}

void edaSerialize::Serialize(edaBuffer &buf, bool pack)
{}

static edaSerialize* classGenerate(int clsid)
{
  switch (clsid){
  case (_SYSCLASSID_ + _CLSID_EDAHC_):
    return (edaSerialize *)new edaHC();
    
  case (_SYSCLASSID_ + _CLSID_EDASA_):
    return (edaSerialize *)new edaSA();
    
  /*
  case (_SYSCLASSID_ + _CLSID_EDAMOVE_):
    return (edaSerialize *)new edaMove();
  */
  /*
  case (_SYSCLASSID_ + _CLSID_EDAMOVEGEN_):
    return (edaSerialize *)new edaMoveGen();
  */

  case (_SYSCLASSID_ + _CLSID_EDAHCMOVEEXPL_):
    return (edaSerialize *)new edaHCMoveExpl();

/*
  case (_SYSCLASSID_ + _CLSID_EDAMOVESELECT_):
    return (edaSerialize *)new edaMoveSelect();
*/

  case (_SYSCLASSID_ + _CLSID_EDABESTIMPRSELECT_):
    return (edaSerialize *)new edaBestImprSelect();

  case (_SYSCLASSID_ + _CLSID_EXP_COOLING_SCHEDULE_):
    return (edaSerialize *)new edaExpCoolingSchedule;
  case (_SYSCLASSID_ + _CLSID_LINEAR_COOLING_SCHEDULE_):
    return (edaSerialize *)new edaLinearCoolingSchedule;

  case (_SYSCLASSID_ + _CLSID_GEN_CONTINUE_):
    return (edaSerialize *)new edaGenContinue;

  case (_SYSCLASSID_ + _CLSID_FIT_CONTINUE_):
    return (edaSerialize *)new edaFitContinue;

  // Tabu search
  case (_SYSCLASSID_ + _CLSID_EDATS_):
    return (edaSerialize *)new edaTS;

/*
  case (_SYSCLASSID_ + _CLSID_EDATABULIST_):
    return (edaSerialize *)new edaTabuList;
*/
  case (_SYSCLASSID_ + _CLSID_EDATSMOVEEXPL_):
    return (edaSerialize *)new edaTSMoveExpl;
/*
  case (_SYSCLASSID_ + _CLSID_EDAASPIRCRIT_):
    return (edaSerialize *)new edaAspirCrit;
*/
  case (_SYSCLASSID_ + _CLSID_EDANOASPIRCRIT_):
    return (edaSerialize *)new edaNoAspirCrit;

  case (_SYSCLASSID_ + _CLSID_EDAIMPRBESTFITASPIRCRIT_):
    return (edaSerialize *)new edaImprBestFitAspirCrit;

  case (_SYSCLASSID_ + _CLSID_EDASIMPLEMOVETABULIST_):
    return (edaSerialize *)new edaSimpleMoveTabuList;

  case (_SYSCLASSID_ + _CLSID_EDASIMPLESOLUTIONTABULIST_):
    return (edaSerialize *)new edaSimpleSolutionTabuList;

  default:
    return userClassGenerate(clsid);
  }
}

#pragma weak userClassGenerate
edaSerialize *userClassGenerate( int clsid )
{
  std::cerr << "User must override userClassGenerate()" << std::endl;
  exit(-1);
}

edaSerialize *classGenerateFromBuffer( edaBuffer &buf )
{
  int clsid;
  edaSerialize *obj;
  
  // unpack the ID
  buf.UnPack( &clsid, 1 );

  // generate the object
  obj = classGenerate( clsid );
  obj->Serialize( buf, false );

  // return
  return obj;
}

